﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
// Experimental, probably inefficient - not sure this is used anywhere.
using System;
using System.Threading;

namespace BrainTechLLC
{
    public class Parallelizer
    {
        public int _threadCount;
        private Action _parallelAction;
        public Thread[] _threads;
        public bool _wantExit;
        public AutoResetEvent _wait = new AutoResetEvent(false);
        public AutoResetEvent _done = new AutoResetEvent(false);

        public void ParallelExecute(Action action1, Action action2)
        {
            ParallelAction = action1;
            action2();
            _done.WaitOne();
        }

        public Action ParallelAction
        {
            set
            {
                if (_parallelAction != null)
                    throw new Exception("Parallel action already scheduled");

                Interlocked.CompareExchange<Action>(ref _parallelAction, value, null);

                _wait.Set();
            }
        }

        public Parallelizer()
        {
            _threadCount = 2;
            _threads = new Thread[_threadCount - 1];

            for (int n = 0; n < _threadCount - 1; n++)
            {
                ThreadStart ts = new ThreadStart(Worker);
                _threads[n] = new Thread(ts)
                {
                    IsBackground = true,
#if NO_SILVERLIGHT
                    //ApartmentState = ApartmentState.MTA,
                    Priority = ThreadPriority.Normal,
#endif
                    Name = "Parallelizer worker thread"

                };
                _threads[n].Start();
            }
        }

        public void Worker()
        {
            while (!_wantExit)
            {
                _wait.WaitOne();

                if (_parallelAction != null)
                {
                    Action action = Interlocked.Exchange<Action>(ref _parallelAction, null);
                    action();
                    _done.Set();
                }
            }
        }
    }
}